#include<iostream>
#include<functional>
#include<vector>
#include<unordered_map>
#include<memory>
#include<cstdint>
#include<unistd.h>
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class Timetask
{
public:
    Timetask(uint64_t id,int timeout,const TaskFunc& cb):_id(id),_timeout(timeout),_cb(cb),cmz(false)
    {
    }
    ~Timetask()
    {
        if(cmz==false) _cb();
        _release();
    }
    void Cancel() {cmz=true;}
    void SetRelease(const ReleaseFunc& release)
    {
        _release=release;
    }
    int Delaytime()
    {
        return _timeout;
    }
private:
    uint64_t _id;//定时器任务对象id
    int _timeout;//超时时间
    TaskFunc _cb;//超时执行任务
    bool cmz;//false表是没取消，true取消了
    ReleaseFunc _release; //用于删除TimerWheel中保存的定时器对象信息,指针彻底释放完后
};

class Timewheel
{
public:
    Timewheel(int t=0,int capacity=60):tick(0),_capacity(capacity),_wheel(_capacity)
    {}
private:
    using Weaktask=std::weak_ptr<Timetask>;
    using Ptrtask=std::shared_ptr<Timetask>;
    int tick;//秒钟
    int _capacity;//表盘最大数量，最大延迟时间
    std::vector<std::vector<Ptrtask>> _wheel;
    std::unordered_map<uint64_t,Weaktask> _timers;
private:
    void Remove(uint64_t id)//移除
    {
        auto it=_timers.find(id);
        if(it==_timers.end())
        {
            return ;
        }
        _timers.erase(it);
    }
public:
    void TimeAdd(uint64_t id,int timeout,const TaskFunc& cb)
    {
        Ptrtask pt(new Timetask(id,timeout,cb));
        pt->SetRelease(std::bind(&Timewheel::Remove,this,id));
        _timers[id]=Weaktask(pt);

        int pos=(tick+timeout)%_capacity;
        _wheel[pos].push_back(pt);

    }
    void TimeRefresh(uint64_t id)
    {
        auto it=_timers.find(id);
        if(it==_timers.end())
        {
            return ;//没有定时任务，不刷新
        }
        Ptrtask pt=it->second.lock();//weak_ptr转为shared_ptr
        int timeout=pt->Delaytime();
        int pos=(tick+timeout)%_capacity;
        _wheel[pos].push_back(pt);
    }
    void TimeCancel(uint64_t id)
    {
        auto it=_timers.find(id);
        if(it==_timers.end())
        {
            return ;
        }
        Ptrtask pt=it->second.lock();
        if(pt) pt->Cancel();
    }
    void RunTimerTask()
    {
        tick=(tick+1)%_capacity;
        _wheel[tick].clear();//清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
    }
};

class Test {
    public:
        Test() {std::cout << "构造" << std::endl;}
        ~Test() {std::cout << "析构" << std::endl;}
};

void DelTest(Test *t) {
    delete t;
}

int main()
{
    Timewheel tw;

    Test *t = new Test();

    tw.TimeAdd(888, 5, std::bind(DelTest, t));

    for(int i = 0; i < 5; i++) {
        sleep(1);
        tw.TimeRefresh(888);//刷新定时任务
        tw.RunTimerTask();//向后移动秒针
        std::cout << "刷新了一下定时任务，重新需要5s中后才会销毁\n";
    }
    tw.TimeCancel(888);
    while(1) {
        sleep(1);
        std::cout << "-------------------\n";
        tw.RunTimerTask();//向后移动秒针
    }
    return 0;
}
// int main()
// {
//     TimerWheel tw;
//     Test *t = new Test();
//     tw.TimerAdd(888, 5, std::bind(DelTest, t));

//     for(int i = 0; i < 5; i++) {
//         sleep(1);
//         if (i < 3) { // 前3次刷新任务，第4次开始停止刷新
//             tw.TimerRefresh(888);
//             std::cout << "刷新任务，需5秒后执行\n";
//         } else if (i == 3) { // 第4次循环时主动取消
//             tw.TimerCancel(888);
//             std::cout << "已取消任务，后续不再执行\n";
//         }
//         tw.RunTimerTask();
//     }

//     while(1) {
//         sleep(1);
//         std::cout << "-------------------\n";
//         tw.RunTimerTask();
//     }
//     return 0;
// }